﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;
using System.Reflection;

using PickGold.Collections;

namespace PickGold.Attributes
{
	/// <summary>
	/// 指示方法属性事件或托管为委托执行类型
	/// </summary>
	[Serializable]
	[DataContract]
	[ComVisible(true)]
	[ClassInterface(ClassInterfaceType.AutoDispatch)]
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Delegate | AttributeTargets.Class)]
	public class DelegateAttribute : Attribute
	{
		/// <summary>
		/// 相对类型所在的程序集名称
		/// </summary>
		[DataMember]
		internal string InnerAssemblyName;

		/// <summary>
		/// 相对类型名称
		/// </summary>
		[DataMember]
		internal string InnerTypeName;

		/// <summary>
		/// 附加数据，一般为当前标志所在方法属性事件委托等的名称
		/// </summary>
		[DataMember]
		internal object InnerTag;

		/// <summary>
		/// Level
		/// </summary>
		[DataMember]
		private int _Level;

		/// <summary>
		/// Type
		/// </summary>
		[NonSerialized]
		private Type _Type;

		/// <summary>
		/// NameTypeCollection
		/// </summary>
		[NonSerialized]
		private static NameObjectCollection _NameTypeCollection;

		/// <summary>
		/// 构造一表示委托执行类型的实例
		/// </summary>
		public DelegateAttribute()
		{
			this._Type = null;
			this.InnerAssemblyName = null;
			this.InnerTypeName = null;
			this.InnerTag = null;
			this._Level = 0;
		}

		/// <summary>
		/// 构造一表示委托执行类型的实例
		/// </summary>
		/// <param name="type">相对类型，如当前方法属性事件或托管的声明类型原型为方法或基类型</param>
		public DelegateAttribute(Type type)
		{
			this._Type = type;
			this.InnerAssemblyName = type.Assembly.FullName;
			this.InnerTypeName = type.FullName;
			this.InnerTag = null;
			this._Level = 0;
			if (DelegateAttribute.InnerNameTypeCollection[type.FullName] == null)
				DelegateAttribute.InnerNameTypeCollection[type.FullName] = type;
		}

		/// <summary>
		/// 构造一表示委托执行类型的实例
		/// </summary>
		/// <param name="type">相对类型，如当前方法属性事件或托管的声明类型原型为方法或基类型</param>
		public DelegateAttribute(string type)
		{
			this._Type = null;
			this.InnerAssemblyName = null;
			this.InnerTypeName = type;
			this.InnerTag = null;
			this._Level = 0;
		}

		/// <summary>
		/// 构造一表示委托执行类型的实例
		/// </summary>
		/// <param name="level">调用等级。零为自动；负数为原型声明；正数为定义，可调用代码段；绝对值相等或为零方可委托运行</param>
		public DelegateAttribute(int level)
		{
			this._Type = null;
			this.InnerAssemblyName = null;
			this.InnerTypeName = null;
			this.InnerTag = null;
			this._Level = level;
		}

		/// <summary>
		/// 构造一表示委托执行类型的实例
		/// </summary>
		/// <param name="isDeclare">是否为原型声明；绝对值为 1 的调用等级；</param>
		public DelegateAttribute(bool isDeclare)
		{
			this._Type = null;
			this.InnerAssemblyName = null;
			this.InnerTypeName = null;
			this.InnerTag = null;
			this._Level = isDeclare ? -1 : 1;
		}

		/// <summary>
		/// 构造一表示委托执行类型的实例
		/// </summary>
		/// <param name="type">相对类型，如当前方法属性事件或托管的声明类型原弄为方法或基类型</param>
		/// <param name="level">调用等级。零为自动；负数为原型声明；正数为定义，可调用代码段；绝对值相等或为零方可委托运行</param>
		public DelegateAttribute(Type type, int level)
		{
			this._Type = type;
			this.InnerAssemblyName = type.Assembly.FullName;
			this.InnerTypeName = type.FullName;
			this.InnerTag = null;
			this._Level = level;
			if (DelegateAttribute.InnerNameTypeCollection[type.FullName] == null)
				DelegateAttribute.InnerNameTypeCollection[type.FullName] = type;
		}

		/// <summary>
		/// 构造一表示委托执行类型的实例
		/// </summary>
		/// <param name="type">相对类型，如当前方法属性事件或托管的声明类型原弄为方法或基类型</param>
		/// <param name="isDeclare">是否为原型声明；绝对值为 1 的调用等级；</param>
		public DelegateAttribute(Type type, bool isDeclare)
		{
			this._Type = type;
			this.InnerAssemblyName = type.Assembly.FullName;
			this.InnerTypeName = type.FullName;
			this.InnerTag = null;
			this._Level = isDeclare ? -1 : 1;
			if (DelegateAttribute.InnerNameTypeCollection[type.FullName] == null)
				DelegateAttribute.InnerNameTypeCollection[type.FullName] = type;
		}

		/// <summary>
		/// 构造一表示委托执行类型的实例
		/// </summary>
		/// <param name="type">相对类型，如当前方法属性事件或托管的声明类型原弄为方法或基类型</param>
		/// <param name="level">调用等级。零为自动；负数为原型声明；正数为定义，可调用代码段；绝对值相等或为零方可委托运行</param>
		public DelegateAttribute(string type, int level)
		{
			this._Type = null;
			this.InnerAssemblyName = null;
			this.InnerTypeName = type;
			this.InnerTag = null;
			this._Level = level;
		}

		/// <summary>
		/// 构造一表示委托执行类型的实例
		/// </summary>
		/// <param name="type">相对类型，如当前方法属性事件或托管的声明类型原弄为方法或基类型</param>
		/// <param name="isDeclare">是否为原型声明；绝对值为 1 的调用等级；</param>
		public DelegateAttribute(string type, bool isDeclare)
		{
			this._Type = null;
			this.InnerAssemblyName = null;
			this.InnerTypeName = type;
			this.InnerTag = null;
			this._Level = isDeclare ? -1 : 1;
		}

		/// <summary>
		/// 相对类型所在的程序集名称
		/// </summary>
		public string AssemblyName
		{
			get
			{
				return this.InnerAssemblyName;
			}
		}

		/// <summary>
		/// 相对类型名称
		/// </summary>
		public string TypeName
		{
			get
			{
				return this.InnerTypeName;
			}
		}

		/// <summary>
		/// 调用等级。零为自动；负数为原型声明；正数为定义，可调用代码段；绝对值相等或为零方可委托运行
		/// </summary>
		public int Level
		{
			get
			{
				return this._Level;
			}
		}

		/// <summary>
		/// 当在派生类中重写时，返回一个指示此实例是否等于指定对象的值。
		/// </summary>
		/// <param name="obj">与 System.Attribute 的此实例进行比较的 System.Object。</param>
		/// <returns>如果该实例等于 obj，则为 true；否则，为 false。</returns>
		public override bool Match(object obj)
		{
			DelegateAttribute a = obj as DelegateAttribute;
			if (a == null)
				return base.Match(obj);

			if (this.InnerAssemblyName != a.InnerAssemblyName)
				return false;

			if (this.InnerTypeName != a.InnerTypeName)
				return false;

			if (this.InnerTag != a.InnerTag)
				return false;

			if (this._Level != a._Level)
				return false;

			return true;
		}

		/// <summary>
		/// 返回一个值，该值指示此实例是否与指定的对象相等。
		/// </summary>
		/// <param name="obj">要与此实例进行比较的 System.Object 或 null。</param>
		/// <returns>如果 obj 等于此实例的类型和值，则为 true；否则为 false。</returns>
		public override bool Equals(object obj)
		{
			DelegateAttribute a = obj as DelegateAttribute;
			if (a == null)
				return base.Equals(obj);

			if (this.InnerAssemblyName != a.InnerAssemblyName)
				return false;

			if (this.InnerTypeName != a.InnerTypeName)
				return false;

			if (this.InnerTag != a.InnerTag)
				return false;

			if (this._Level != a._Level)
				return false;

			return true;
		}

		/// <summary>
		/// 返回该字符串的哈希代码。
		/// </summary>
		/// <returns>32 位有符号整数哈希代码。</returns>
		public override int GetHashCode()
		{
			string t = this.InnerAssemblyName + Environment.NewLine + this.InnerTypeName + Environment.NewLine + this.InnerTag + Environment.NewLine + this._Level;
			return t.GetHashCode();
		}

		/// <summary>
		/// 内部静态类型缓存
		/// </summary>
		internal static NameObjectCollection InnerNameTypeCollection
		{
			get
			{
				if (DelegateAttribute._NameTypeCollection == null)
					DelegateAttribute._NameTypeCollection = new NameObjectCollection();

				return DelegateAttribute._NameTypeCollection;
			}
		}

		/// <summary>
		/// 获取指定类别中所有标记有 DelegateAttribute 属性的成员
		/// </summary>
		/// <param name="type">指定的类别</param>
		/// <param name="level">指定的调用等级</param>
		/// <returns>指定类别中所有标记有 DelegateAttribute 属性的成员</returns>
		public static MethodBase[] GetMembers(Type type, int level)
		{
			return DelegateAttribute.GetMembers(type, level, true);
		}
		/// <summary>
		/// 获取指定类别中所有标记有 DelegateAttribute 属性的成员
		/// </summary>
		/// <param name="type">指定的类别</param>
		/// <param name="level">指定的调用等级</param>
		/// <param name="inherit">是否包括继承属性</param>
		/// <returns>指定类别中所有标记有 DelegateAttribute 属性的成员</returns>
		public static MethodBase[] GetMembers(Type type, int level, bool inherit)
		{
			var ms = type.GetMethods();
			var ls = new List<MethodBase>();
			foreach (var m in ms)
			{
				var os = type.GetCustomAttributes(typeof(DelegateAttribute), inherit) as DelegateAttribute[];
				foreach (var o in os)
				{
					if (o._Level == level)
					{
						ls.Add(m);
						break;
					}
				}
			}
			return ls.ToArray();
		}
	}
}
